/*
Kakine
ActionScript Framework
Copyright © 2011, PUNY, LLC.

This file is part of KAKINE.

KAKINE is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

KAKINE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with KAKINE.  If not, see <http://www.gnu.org/licenses/>.
*/ 
package com.puny.ball.utils
{
	import flash.geom.Point;
	
	/**
	 * Collision between Particle and Line 
	 * @author toritori
	 * 
	 */
	public class CollisionPL extends Object implements ICollision	{
		private const _r:Vector2D = new Vector2D();
		private const _a:Vector2D = new Vector2D();
		private const _p:Vector2D = new Vector2D();
		private const _p0:Vector2D = new Vector2D();
		private const _pt:Vector2D = new Vector2D();
		private const _pt0:Vector2D = new Vector2D();
		private const _reflex:Vector2D = new Vector2D();
		private const _mirror:Vector2D = new Vector2D();
		private var _determinant:Number;
		private var _al2:Number;
		private var _t:Number;
		private var _e:Number = 1;
		public function CollisionPL() {
		}
		
		public function get dir():Vector2D {
			return _a;
		}
		public function set dir(a:Vector2D):void {
			_a.x = a.x;
			_a.y = a.y;
			var al:Number = _a.length;
			_al2 = al * al;
		}
		
		public function set e(value:Number):void {
			_e = value > 1 ?  1: (value < 0 ? 0 : value);
		}
		
		public function get r():Vector2D {
			return _r;
		}
		public function set r(r:Vector2D):void {
			_r.x = r.x;
			_r.y = r.y;
		}
		/**
		 * 
		 * @param p0
		 * @param p
		 * @return <code>true</code> if a collision would happen. Otherwise, <code>false</code>
		 * 
		 */
		public function setParticle(p0:Vector2D,p:Vector2D):Boolean {
			_determinant = - _a.x * p.y + p.x * _a.y;
			_p.x = p.x;
			_p.y = p.y;
			_p0.x = p0.x;
			_p0.y = p0.y;
			return _determinant != 0;
		} 
		
		protected function get determinant():Number {
			return _determinant;
		}
		
		public function collisionPoint():Number {
//			trace("a=",_a);
//			trace("r=",_r);
//			trace("p0=",_p0);
//			trace("p=",_p);
			var prx:Number = (_p0.x - _r.x) / determinant;
			var pry:Number = (_p0.y - _r.y) / determinant;
			var s:Number = -_p.y * prx + _p.x * pry;
			var t:Number = -_a.y * prx + _a.x * pry;
			if ( 0 <= s && s <= 1 && 0 <= t && t <= 1) {
				_t = t;
				_pt.x = _p.x *_t;
				_pt.y = _p.y *_t;
				_pt0.x = _p0.x + _pt.x;
				_pt0.y = _p0.y + _pt.y;
//				trace("t=",t);
				return t;
			}
			return NaN;
		}
		
		public function collisionPos():Point {
			return _pt0;
		}
		
		public function reflex():Vector2D {
//			if (_t > .9) {
//				trace("_bingo");
//			}

			var t:Number = _t == 1 ? .1 : 1 - _t;
//			var p:Point = _p.multiply(t);
			_reflex.x = _p.x * t;
			_reflex.y = _p.y * t;
			var s:Number = (1+_e) * _a.dot(_reflex) / _al2;
			_reflex.x = _a.x * s - _e*_reflex.x + _pt0.x;
			_reflex.y = _a.y * s - _e*_reflex.y + _pt0.y;
			return _reflex;
//			return _a.multiply(2 * _a.dot(p) / _al2).subtract(p).add(_pt0) as Vector2D;
		}
				
		public function mirror():Vector2D {
//			var p0:Point = _pt0.add(_pt);
//			return _pt.subtract(_a.multiply(2 * _a.dot(_pt) / _al2)).add(_pt0) as Vector2D;			
			var t:Number = 2 * _a.dot(_pt) / _al2;
			_mirror.x = _pt.x - _a.x * t + _pt0.x;
			_mirror.y = _pt.y - _a.y * t + _pt0.y; 
			return _mirror;
		}
		
	}
}